/*
*    Phantom v2.0 GUI Automation Software
*    Copyright (C) 2009  John C. Van Arsdall (john@phantomtest.com)
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include ".\ssi_dataptdoutput.h"
#include ".\dataptd.h"

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

SSI_INT64 CDataPTDOutput::sType = 0;

jmethodID CDataPTDOutput::getOutputID = 0;
jmethodID CDataPTDOutput::getChildCountID = 0;
jmethodID CDataPTDOutput::getChildID = 0;
jmethodID CDataPTDOutput::getErrorCountID = 0;
jmethodID CDataPTDOutput::getWarningCountID = 0;
jmethodID CDataPTDOutput::getNameID = 0;
jmethodID CDataPTDOutput::getParentID = 0;
jmethodID CDataPTDOutput::hasParentID = 0;
jmethodID CDataPTDOutput::saveAsTextID = 0;
jmethodID CDataPTDOutput::saveAsHTMLID = 0;
jmethodID CDataPTDOutput::getRemoteMachineID = 0;
jmethodID CDataPTDOutput::haltExecutionID = 0;

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

CDataPTDOutput::CDataPTDOutput(void)
{
  if(!sType){
		sType = 1;
		sType = Factory_RegisterData((CData*)new CDataPTDOutput());
	}
	Type = sType;
	DataName = "ptdoutput";

  my_obj = 0;
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

CDataPTDOutput::~CDataPTDOutput(void)
{
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

SSI_BOOL CDataPTDOutput::CopyData(CData* Other)
{
  CDataPTDOutput* O = (CDataPTDOutput*)Other;
  my_obj = O->my_obj;

  return 1;
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

CData* CDataPTDOutput::MakeData(void)
{
	return (CData*) new CDataPTDOutput();
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

SSI_BOOL CDataPTDOutput::DeleteData(CData* In)
{
	delete ((CDataPTDOutput*)In);
	return 1;
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

SSI_BOOL CDataPTDOutput::DataFromString(const String& sData)
{
	return 0;
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

String CDataPTDOutput::GetString(void)
{
	String Ret = "PTD Output";
	return Ret;
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

SSI_INT64 CDataPTDOutput::SizeOf(void)
{
	return 0;
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

SSI_INT64 CDataPTDOutput::GetRegisteredType(void)
{
	return sType;
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

CStatus CDataPTDOutput::InitData(void)
{
	CFunctionDecl aNewFunc;
  
  aNewFunc.Name = "getOutput";
  aNewFunc.ReturnType = CDataString::GetRegisteredType();
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);

  aNewFunc.Clear();
  aNewFunc.Name = "getChildCount";
  aNewFunc.ReturnType = CDataInt::GetRegisteredType();
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);

  aNewFunc.Clear();
  aNewFunc.Name = "getChild";
  aNewFunc.ReturnType = CDataPTDOutput::GetRegisteredType();
  aNewFunc.addType(CDataInt::GetRegisteredType());
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);

  aNewFunc.Clear();
  aNewFunc.Name = "getErrorCount";
  aNewFunc.ReturnType = CDataInt::GetRegisteredType();
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);

  aNewFunc.Clear();
  aNewFunc.Name = "getWarningCount";
  aNewFunc.ReturnType = CDataInt::GetRegisteredType();
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);

  aNewFunc.Clear();
  aNewFunc.Name = "getParent";
  aNewFunc.ReturnType = CDataPTDOutput::GetRegisteredType();
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);
  
  aNewFunc.Clear();
  aNewFunc.Name = "hasParent";
  aNewFunc.ReturnType = CDataBool::GetRegisteredType();
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);

  aNewFunc.Clear();
  aNewFunc.Name = "getName";
  aNewFunc.ReturnType = CDataString::GetRegisteredType();
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);

  aNewFunc.Clear();
  aNewFunc.Name = "saveAsHTML";
  aNewFunc.ReturnType = CDataBool::GetRegisteredType();
  aNewFunc.addType(CDataString::GetRegisteredType());
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);

  aNewFunc.Clear();
  aNewFunc.Name = "saveAsText";
  aNewFunc.ReturnType = CDataBool::GetRegisteredType();
  aNewFunc.addType(CDataString::GetRegisteredType());
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);

  aNewFunc.Clear();
  aNewFunc.Name = "getRemoteMachine";
  aNewFunc.ReturnType = CDataString::GetRegisteredType();
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);

  aNewFunc.Clear();
  aNewFunc.Name = "haltExecution";
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);


  /*
  aNewFunc.Clear();
  aNewFunc.Name = "getName";
  aNewFunc.ReturnType = CDataString::GetRegisteredType();
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);

  aNewFunc.Clear();
  aNewFunc.Name = "getType";
  aNewFunc.ReturnType = CDataString::GetRegisteredType();
	aNewFunc.SetProcessor(this);
	AddFunction(aNewFunc);
*/

	//aNewFunc.Name = "Save";
  //aNewFunc.ReturnType = CDataBool::GetRegisteredType();
	//aNewFunc.addType(CDataString::GetRegisteredType());
	//aNewFunc.SetProcessor(this);
	//AddFunction(aNewFunc);

	//aNewFunc.Clear();
	//aNewFunc.Name = "Load";
	//aNewFunc.ReturnType = CDataBool::GetRegisteredType();
	//aNewFunc.addType(CDataString::GetRegisteredType());
	//aNewFunc.SetProcessor(this);
	//AddFunction(aNewFunc);

////
//	CVariable aVar;
//	aVar.Name = "Tag";
//	aVar.SetType(CDataString::GetRegisteredType());
//	AddVariable(aVar);

//	aVar.Name = "Class";
//	aVar.SetType(CDataString::GetRegisteredType());
//	AddVariable(aVar);

	return STAT_OK;
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

void CDataPTDOutput::SSI_FunctionProcessor(SSI_FunctionAPI& theAPI)
{
  // Initial Errors
  if(my_obj == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: my_obj");
      return;
  }

  if(CDataPTD::env == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: env");
      return;
  }

  //static jmethodID getChildCountID;
  //static jmethodID getChildID;
  //static jmethodID getErrorCountID;
  //static jmethodID getWarningCountID;


  if(theAPI.m_FunctionName == "getOutput"){
    if(getOutputID == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
      return;
    }

		CDataString ret;
    
    // Call the function and get the string
    jstring j = (jstring)CDataPTD::env->CallObjectMethod(my_obj, getOutputID);
    if(j == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: could not get output");
      return;
    }
    const char *str = CDataPTD::env->GetStringUTFChars(j, 0);
    if(str){
      ret.Data.Format("%s", str);
    }
    CDataPTD::env->ReleaseStringUTFChars(j, str);

    theAPI.m_ReturnStatus = STAT_OK;
    theAPI.SetReturnData(&ret);
		return;
  }else if(theAPI.m_FunctionName == "getChildCount"){
    if(getChildCountID == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
      return;
    }
    jint i = CDataPTD::env->CallIntMethod(my_obj, getChildCountID);
    CDataInt ret;
    ret.Data = i;
    theAPI.SetReturnData(&ret);

  }else if(theAPI.m_FunctionName == "getChild"){
    if(getChildID == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
      return;
    }

		CDataInt i;
		i.Data = SSI_EXTRACT(CDataInt, 0);

    CDataPTDOutput ret;
    
    jobject outp = CDataPTD::env->CallObjectMethod(my_obj, getChildID, i.Data);
    if(outp == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTD Output processor error: Output %i not available", i.Data);
      return;
    }
    ret.my_obj = outp;
    theAPI.SetReturnData(&ret);
    theAPI.m_ReturnStatus = STAT_OK;
  }else if(theAPI.m_FunctionName == "getErrorCount"){
    if(getErrorCountID == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
      return;
    }
    jint i = CDataPTD::env->CallIntMethod(my_obj, getErrorCountID);
    CDataInt ret;
    ret.Data = i;
    theAPI.SetReturnData(&ret);

  }else if(theAPI.m_FunctionName == "getWarningCount"){
    if(getWarningCountID == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
      return;
    }
    jint i = CDataPTD::env->CallIntMethod(my_obj, getWarningCountID);
    CDataInt ret;
    ret.Data = i;
    theAPI.SetReturnData(&ret);
  }else if(theAPI.m_FunctionName == "getName"){
    if(getNameID == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
      return;
    }
    CDataString ret;

    jstring j = (jstring)CDataPTD::env->CallObjectMethod(my_obj, getNameID);
    if(j == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: could not get name");
      return;
    }
    const char *str = CDataPTD::env->GetStringUTFChars(j, 0);
    if(str){
      ret.Data.Format("%s", str);
    }
    CDataPTD::env->ReleaseStringUTFChars(j, str);

    theAPI.m_ReturnStatus = STAT_OK;
    theAPI.SetReturnData(&ret);
  }else if(theAPI.m_FunctionName == "hasParent"){
    if(hasParentID == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
      return;
    }
    jboolean b = CDataPTD::env->CallBooleanMethod(my_obj, hasParentID);
    CDataBool ret;
    ret.Data = b;
    theAPI.SetReturnData(&ret);
  }else if(theAPI.m_FunctionName == "getParent"){
    if(getParentID == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
      return;
    }
		CDataPTDOutput ret;
    
    // Call the method
    jobject outp = CDataPTD::env->CallObjectMethod(my_obj, getParentID);
    if(outp == 0){
      theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor error: output has no parent");
      return;
    }
    ret.my_obj = outp;
    theAPI.SetReturnData(&ret);
		return;
    }else if(theAPI.m_FunctionName == "saveAsHTML"){
      if(saveAsHTMLID == 0){
        theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
        return;
      }
      CDataString s;
      s.Data = SSI_EXTRACT(CDataString, 0);
      jstring j = CDataPTD::env->NewStringUTF(s.Data.Str());
      
      jboolean b = CDataPTD::env->CallBooleanMethod(my_obj, saveAsHTMLID, j);
      CDataBool ret;
      ret.Data = b;
      theAPI.SetReturnData(&ret);
    }else if(theAPI.m_FunctionName == "saveAsText"){
      if(saveAsTextID == 0){
        theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
        return;
      }
      CDataString s;
      s.Data = SSI_EXTRACT(CDataString, 0);
      jstring j = CDataPTD::env->NewStringUTF(s.Data.Str());

      jboolean b = CDataPTD::env->CallBooleanMethod(my_obj, saveAsTextID, j);
      CDataBool ret;
      ret.Data = b;
      theAPI.SetReturnData(&ret);
    }else if(theAPI.m_FunctionName == "getRemoteMachine"){
      if(getRemoteMachineID == 0){
        theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
        return;
      }
      CDataString ret;

      jstring j = (jstring)CDataPTD::env->CallObjectMethod(my_obj, getRemoteMachineID);
      if(j == 0){
        theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: could not get remote machine name");
        return;
      }
      const char *str = CDataPTD::env->GetStringUTFChars(j, 0);
      if(str){
        ret.Data.Format("%s", str);
      }
      CDataPTD::env->ReleaseStringUTFChars(j, str);

      theAPI.m_ReturnStatus = STAT_OK;
      theAPI.SetReturnData(&ret);
    }else if(theAPI.m_FunctionName == "haltExecution"){
      if(haltExecutionID == 0){
        theAPI.m_ReturnStatus.Format(STAT_ERR, "PTDOutput processor internal error: %s", theAPI.m_FunctionName.Str());
        return;
      }
      CDataPTD::env->CallVoidMethod(my_obj, haltExecutionID);
      if(theAPI.m_Engine){
        theAPI.m_Engine->GetOutStream()->Disp("** Execution halted by ptdoutput **", 1);
        theAPI.m_Engine->GetInterpreter()->SetStopFlag();
      }
      theAPI.m_ReturnStatus = STAT_OK;
    }

}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

SSI_INT64 CDataPTDOutput::Register(SSI_INT64 NewType){
	sType = NewType;
	return 1;
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

void CDataPTDOutput::UnRegister(){
	sType = 0;
}

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

CData* CDataPTDOutput::operator_equal(CData* InData, OpInfoT* Info)
{
	CopyData(InData);
	return (CData*)this;
}
